//generic function
let lastNumber = <T>(array:Array<T>) => {
    return array[array.length-1];
};

const l1=lastNumber([1,2,3,4]);
const l2=lastNumber<string|number>(['a','b','c']);

let point1=<T,Y>(x:T, y:Y) => [x,y];
const v1=point1(1,'one');
const v2=point1<boolean,number>(true,1);

let point2=<T,Y=number>(x:T,y:Y) => [x,y];
const v3=point2<number>(1,1);
const v4=point2<number,string>(1,'one');

//generic interface
interface F{
    <T>(arg:T):T;
}
function f<T>(arg:T):T{
    return arg;
}
let ff:F=f;

interface G<T>{
    (arg:T):T;
}
let g:G<number>=f;

//genercis class
class A<T>{
    public list:T[]=[];
    public sum():T{
        if(this.list.length == 0){
            return null as T;
        }else{
            return (this.list as number[]).reduce((x,y)=>x+y) as T;
        }
    }
    public add(element:T){
        this.list.push(element);
    }
}

//generic constraint
interface B{
    title:string;
    content:string;
}
interface C{
    url:string;
}
class D<T extends B&C>{
    private prop:T;
    constructor(arg:T){
        this.prop=arg;
    };
    info(){
        return {
            url:this.prop.url,
            title:this.prop.title,
            content:this.prop.content
        };
    };
}
